package com.small.sentinel.slots.clusterBuilder;

import com.small.common.core.spi.Spi;
import com.small.common.designPattern.behavioral.chainOfResponsibility.slotchain.AbstractLinkedProcessorSlot;
import com.small.sentinel.Constants;
import com.small.sentinel.node.ClusterNode;
import com.small.sentinel.node.DefaultNode;
import com.small.sentinel.slotchain.ResourceWrapper;
import com.small.sentinel.slots.SentinelResource;

import java.util.HashMap;
import java.util.Map;

@Spi(isSingleton = false, order = Constants.ORDER_CLUSTER_BUILDER_SLOT)
public class ClusterBuilderSlot  extends AbstractLinkedProcessorSlot<SentinelResource> {

    private static volatile Map<ResourceWrapper, ClusterNode> clusterNodeMap = new HashMap<>();

    private static final Object lock = new Object();

    private volatile ClusterNode clusterNode = null;

    @Override
    public void entry(SentinelResource resource) throws Throwable {
        ResourceWrapper resourceWrapper = resource.getResourceWrapper();
        DefaultNode node = resource.getDefaultNode();
        if(clusterNode == null){
            synchronized (lock){
                if(clusterNode == null){
                    clusterNode = new ClusterNode(resourceWrapper.getName(), resourceWrapper.getResourceType());
                    HashMap<ResourceWrapper, ClusterNode> newMap = new HashMap<>(Math.max(clusterNodeMap.size(), 16));
                    newMap.putAll(clusterNodeMap);
                    newMap.put(node.getId(), clusterNode);

                    clusterNodeMap = newMap;
                }
            }
        }
        node.setClusterNode(clusterNode);
        fireEntry(resource);
    }

    @Override
    public void exit(SentinelResource resource) throws Throwable {
        fireExit(resource);
    }
}
